package com.team2.cyber_eye;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.json.JSONObject;

import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.graphics.Typeface;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.ContextThemeWrapper;
import android.view.Menu;
import android.view.View;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnMapClickListener;
import com.google.android.gms.maps.GoogleMap.OnMyLocationChangeListener;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.Circle;
import com.google.android.gms.maps.model.CircleOptions;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.Polyline;
import com.google.android.gms.maps.model.PolylineOptions;
import com.team2.cyber_eye.ActivityHelpers.DirectionsJSONParser;
import com.team2.cyber_eye.ActivityHelpers.Util;


public class ShowMapView extends FragmentActivity {

	GoogleMap map = null;
	ArrayList<LatLng> markerPoints;
	Circle myCircle;
	JSONObject jObject;
	String mode = "driving";
	private RadioButton rdBtnDriving;
	private RadioButton rdBtnWalking;
	private RadioGroup radioGroup;
	private LatLng origin;
	private LatLng dest;
	private SupportMapFragment fm;
	private Polyline line;
	
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
		this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
		setContentView(R.layout.activity_maps);
		
		Typeface font1 = Typeface.createFromAsset(getAssets(), "CanarsieSlab.ttf");
		
		TextView labelText = (TextView) findViewById(R.id.directionListLabel);
		
		labelText.setTypeface(font1);
		
		ImageButton directionListBtn = (ImageButton) findViewById(R.id.directionListButton);
		
		rdBtnDriving = (RadioButton) findViewById(R.id.drivingDir);
		
		rdBtnWalking = (RadioButton) findViewById(R.id.walkingDir);
		
		radioGroup = (RadioGroup) findViewById(R.id.radioGr);
		
		rdBtnDriving.setChecked(true);
		
		directionListBtn.setOnClickListener(new View.OnClickListener() {
	        @Override
	        public void onClick(View v) {
	            
	        	Intent intent = new Intent(ShowMapView.this, MapDirectionList.class);
	        	if(jObject != null){
	        		intent.putExtra("json", jObject.toString());
		        	startActivity(intent);
	        	}else{
	        		Context context = getApplicationContext();
					CharSequence text = "Wait for the map to load!";
					int duration = Toast.LENGTH_SHORT;

					Toast toast = Toast.makeText(context, text, duration);
					toast.show();
	        	}
	        	
	        }
	    });
		
		ImageButton homeBtn = (ImageButton) findViewById(R.id.homeButton);
		
		homeBtn.setOnClickListener(new View.OnClickListener() {
	        @Override
	        public void onClick(View v) {
	            
	        	Intent intent = new Intent(ShowMapView.this, Home.class);
	        	intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
	        	startActivity(intent);
	        	
	        }
	    });
		
		// Initializing 
		markerPoints = new ArrayList<LatLng>();
		
		Bundle extras = this.getIntent().getExtras();
		
		if(extras != null){
			String originLat = extras.get("originLat").toString();
			
			double oriLat = 0;
			if(originLat != null && originLat.length() > 0){
				oriLat = Double.parseDouble(originLat);
			}
			
			String originLng = extras.get("originLng").toString();
			
			double oriLng = 0;
			
			if(originLng != null && originLng.length() > 0){
				oriLng = Double.parseDouble(originLng);
			}
			
			origin = new LatLng(oriLat, oriLng);
			
			String destinationLat = extras.get("destLat").toString();
			
			double destLat = 0;
			if(destinationLat != null && destinationLat.length() > 0){
				destLat = Double.parseDouble(destinationLat);
			}
			
			String destinationLng = extras.get("destLng").toString();
			
			double destLng = 0;
			
			if(destinationLng != null && destinationLng.length() > 0){
				destLng = Double.parseDouble(destinationLng);
			}
			
			dest = new LatLng(destLat, destLng);
			
			rdBtnDriving.setOnClickListener(new OnClickListener() {
				
				@Override
				public void onClick(View v) {
					
					int id = radioGroup.getCheckedRadioButtonId();
					
					rdBtnDriving = (RadioButton)findViewById(id);
					
					if(rdBtnDriving != null){
						rdBtnDriving.setChecked(true);
						
						mode = "driving";	
						
						rdBtnWalking.setChecked(false);
						
						if(line != null)
							line.remove();
						
						SetUpGoogleMap(origin, dest);
						
						ProcessGoogleMap(origin, dest);
					}							
				}
			});
						
			rdBtnWalking.setOnClickListener(new OnClickListener() {
				
				@Override
				public void onClick(View v) {
					
					int id = radioGroup.getCheckedRadioButtonId();
					
					rdBtnWalking = (RadioButton)findViewById(id);
					
					if(rdBtnWalking != null){
						rdBtnWalking.setChecked(true);
						
						mode = "walking";	
						
						rdBtnDriving.setChecked(false);
						
						if(line != null)
							line.remove();
						
						SetUpGoogleMap(origin, dest);
						
						ProcessGoogleMap(origin, dest);
					}
					
				}
			});
			
			// Getting reference to SupportMapFragment of the activity_main
			fm = (SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.map);
			
			if(map == null){
				
				// Getting Map for the SupportMapFragment
				map = fm.getMap();
				
				if(isGooglePlayServicesInstalled() && isGoogleMapsInstalled())
		        {
					SetUpGoogleMap(origin, dest);
					
					ProcessGoogleMap(origin, dest);
		        }else{
		        	this.finish();
		        }
			}
				
			
		}else{
			Util.DisplayMessage(getApplicationContext(), "Google Map Error - Coordinates missing");
			this.finish();
		}
		
	}
	
	private void SetUpGoogleMap(LatLng origin,LatLng dest){
		
		if (map != null) 
        {
        	//map.setLocationSource(this);

    		// Enable MyLocation Button in the Map
    		map.setMyLocationEnabled(true);	

    		// Creating MarkerOptions
    		MarkerOptions options = new MarkerOptions();

    		// Setting the position of the marker
    		options.position(origin);

    		options.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE));

    		// Add new marker to the Google Map Android API V2
    		map.addMarker(options);

    		// Setting the position of the marker
    		options.position(dest);

    		options.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));

    		// Add new marker to the Google Map Android API V2
    		map.addMarker(options);

    		// Move the camera instantly to hamburg with a zoom of 15.
    		map.moveCamera(CameraUpdateFactory.newLatLngZoom(origin, 20));

    		// Zoom in, animating the camera.
    		map.animateCamera(CameraUpdateFactory.zoomTo(12), 2000, null);
        }	
	}
	
	private boolean isGooglePlayServicesInstalled(){
		int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getApplicationContext());
		  
		  if (resultCode == ConnectionResult.SUCCESS){
			  
		   return true;
		  }else{
		   Util.DisplayMessage(getApplicationContext(), "Google Play Services not installed");
		   return false;
		  }
	}
	
	public boolean isGoogleMapsInstalled()
	{
	    try
	    {
	        ApplicationInfo info = getPackageManager().getApplicationInfo("com.google.android.apps.maps", 0 );
	       if(info == null){
	    	   Util.DisplayMessage(getApplicationContext(), "Google Maps not installed");
	    	   return false;
	       }
	        return true;
	        
	    } 
	    catch(PackageManager.NameNotFoundException e)
	    {
	    	Util.DisplayMessage(getApplicationContext(), "Google Maps not installed");
	        return false;
	    }
	}
	
	private void ProcessGoogleMap(LatLng origin,LatLng dest){
		// Getting URL to the Google Directions API
		String url = getDirectionsUrl(origin, dest, mode);				

		DownloadTask downloadTask = new DownloadTask();

		// Start downloading json data from Google Directions API
		downloadTask.execute(url);
	}
	
	private String getDirectionsUrl(LatLng origin,LatLng dest, String mode){
					
		// Origin of route
		String str_origin = "origin="+origin.latitude+","+origin.longitude;
		
		// Destination of route
		String str_dest = "destination="+dest.latitude+","+dest.longitude;		
		
					
		// Sensor enabled
		String sensor = "sensor=false";			
					
		// Building the parameters to the web service
		String parameters = str_origin+"&"+str_dest+"&"+sensor+"&mode="+mode;
					
		// Output format
		String output = "json";
		
		// Building the url to the web service
		String url = "https://maps.googleapis.com/maps/api/directions/"+output+"?"+parameters;
		
		
		return url;
	}
	
	/** A method to download json data from url */
    private String downloadUrl(String strUrl) throws IOException{
        String data = "";
        InputStream iStream = null;
        HttpURLConnection urlConnection = null;
        try{
                URL url = new URL(strUrl);

                // Creating an http connection to communicate with url 
                urlConnection = (HttpURLConnection) url.openConnection();

                // Connecting to url 
                urlConnection.connect();

                // Reading data from url 
                iStream = urlConnection.getInputStream();

                BufferedReader br = new BufferedReader(new InputStreamReader(iStream));

                StringBuffer sb  = new StringBuffer();

                String line = "";
                while( ( line = br.readLine())  != null){
                        sb.append(line);
                }
                
                data = sb.toString();

                br.close();

        }catch(Exception e){
                Log.d("Exception while downloading url", e.toString());
        }finally{
                iStream.close();
                urlConnection.disconnect();
        }
        return data;
     }

	
	
	// Fetches data from url passed
	private class DownloadTask extends AsyncTask<String, Void, String>{			
				
		// Downloading data in non-ui thread
		@Override
		protected String doInBackground(String... url) {
				
			// For storing data from web service
			String data = "";
					
			try{
				// Fetching the data from web service
				data = downloadUrl(url[0]);
			}catch(Exception e){
				Log.d("Background Task",e.toString());
			}
			return data;		
		}
		
		// Executes in UI thread, after the execution of
		// doInBackground()
		@Override
		protected void onPostExecute(String result) {			
			super.onPostExecute(result);			
			
			ParserTask parserTask = new ParserTask();
			
			// Invokes the thread for parsing the JSON data
			parserTask.execute(result);
				
		}		
	}
	
	/** A class to parse the Google Places in JSON format */
    private class ParserTask extends AsyncTask<String, Integer, List<List<HashMap<String,String>>> >{
    	
    	// Parsing the data in non-ui thread    	
		@Override
		protected List<List<HashMap<String, String>>> doInBackground(String... jsonData) {
				
			List<List<HashMap<String, String>>> routes = null;			           
            
            try{
            	jObject = new JSONObject(jsonData[0]);
            	DirectionsJSONParser parser = new DirectionsJSONParser();
            	
            	// Starts parsing data
            	routes = parser.parse(jObject);    
            }catch(Exception e){
            	e.printStackTrace();
            }
            return routes;
		}
		
		// Executes in UI thread, after the parsing process
		@Override
		protected void onPostExecute(List<List<HashMap<String, String>>> result) {
			ArrayList<LatLng> points = null;
			PolylineOptions lineOptions = null;
			MarkerOptions markerOptions = new MarkerOptions();
			
			// Traversing through all the routes
			for(int i=0;i<result.size();i++){
				points = new ArrayList<LatLng>();
				lineOptions = new PolylineOptions();
				
				// Fetching i-th route
				List<HashMap<String, String>> path = result.get(i);
				
				// Fetching all the points in i-th route
				for(int j=0;j<path.size();j++){
					HashMap<String,String> point = path.get(j);					
					
					double lat = Double.parseDouble(point.get("lat"));
					double lng = Double.parseDouble(point.get("lng"));
					LatLng position = new LatLng(lat, lng);	
					
					points.add(position);						
				}
				
				// Adding all the points in the route to LineOptions
				lineOptions.addAll(points);
				lineOptions.width(5);
				lineOptions.color(Color.GRAY);	
				
			}
			
			// Drawing polyline in the Google Map for the i-th route
			line = map.addPolyline(lineOptions);							
		}			
    } 
    
    /*@Override
    public void onMyLocationChange(Location location) {
     
     LatLng locLatLng = new LatLng(location.getLatitude(), location.getLongitude());
     double accuracy = location.getAccuracy();
     
     if(myCircle == null){
      CircleOptions circleOptions = new CircleOptions()
      .center(locLatLng)   //set center
      .radius(accuracy)   //set radius in meters
      .fillColor(Color.LTGRAY)
      .strokeColor(Color.BLACK)
      .strokeWidth(5);
      
      myCircle = map.addCircle(circleOptions);
     }else{
      myCircle.setCenter(locLatLng);
      myCircle.setRadius(accuracy);
     }
     
     map.animateCamera(CameraUpdateFactory.newLatLng(locLatLng));

    }*/
    
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.global_menu, menu);
		return true;
	}
	
}
